home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / graph3D / graph3D source / g3D_CalcFunc.c < prev    next >
Text File  |  1993-09-17  |  11KB  |  604 lines

  1. /*
  2.     Copyright '89    Christopher Moll
  3.     all rights reserved
  4. */
  5.  
  6.  
  7. #include    "graph3D.h"
  8.  
  9. #ifdef    _LSC3_
  10. #    include    <QuickDraw.h>
  11. #    include    <MemoryMgr.h>
  12. #endif
  13.  
  14.  
  15. extern    Boolean        useMainFunc;
  16.  
  17. extern    int        mainFunct[64];
  18. extern    int        numMnOps;
  19. extern    Real    mnConsts[30];
  20.  
  21. extern    int        derivFunct[64];
  22. extern    int        numDerivOps;
  23. extern    Real    derivConsts[30];
  24.  
  25.  
  26. Real
  27. TheFunction(x, y, z)
  28. Real    x, y, z;
  29. {
  30.     Real    stack[50];
  31. register    int        i, currOp;
  32.     Real        StackOp(), FuncEval(), ArithEval();
  33. register    Real    *stackPtr;
  34.     int        currConst = 0;
  35.     int        numOps;
  36.  
  37.     stackPtr = stack + 49;
  38.     if (useMainFunc)
  39.         if (numMnOps EQ 0)
  40.             return(0.0);
  41.         else
  42.             numOps = numMnOps;
  43.     else
  44.         if (numDerivOps EQ 0)
  45.             return(0.0);
  46.         else
  47.             numOps = numDerivOps;
  48.  
  49.     *stackPtr = 0.0;
  50.     for (i = 0; i < numOps; i++)
  51.     {
  52.         if (useMainFunc)
  53.             currOp = mainFunct[i];
  54.         else
  55.             currOp = derivFunct[i];
  56.         if (IS_PUSH(currOp))
  57.         {
  58.             --stackPtr;
  59.             switch (currOp) {
  60.             case PUSH_X_OP:
  61.                 *stackPtr = x;
  62.                 break;
  63.             case PUSH_Y_OP:
  64.                 *stackPtr = y;
  65.                 break;
  66.             case PUSH_Z_OP:
  67.                 *stackPtr = z;
  68.                 break;
  69.             case PUSH_NUM_OP:
  70.                 if (useMainFunc)
  71.                     *stackPtr = mnConsts[currConst++];
  72.                 else
  73.                     *stackPtr = derivConsts[currConst++];
  74.                 break;
  75.             }
  76.         }
  77.         else if (IS_FUNC(currOp))
  78.             *stackPtr = FuncEval(*stackPtr, currOp);
  79.         else
  80.         {
  81.             stackPtr[1] = ArithEval(stackPtr[1], stackPtr[0], currOp);
  82.             ++stackPtr;
  83.         }
  84.     }
  85.  
  86.     return(*stackPtr);
  87. }
  88.  
  89. static
  90. Real
  91. ArithEval(arg1, arg2, op)
  92. Real    arg1, arg2;
  93. int        op;
  94. {
  95. extern    int    graphType;
  96.  
  97.     switch (op) {
  98.     case MULT_OP:
  99.         return(arg1 * arg2);
  100.     case DIV_OP:
  101.         if (graphType EQ DERIV_GTYPE)
  102.             if (Abs(arg2) > 1e-50)
  103.                 return(arg1 / arg2);
  104.             else
  105.                 return(0.0);
  106.         else
  107.             return(arg1 / arg2);
  108.     case ADD_OP:
  109.         return(arg1 + arg2);
  110.     case SUBT_OP:
  111.         return(arg1 - arg2);
  112.     case MOD_OP:
  113.         return(round(arg1) MOD round(arg2));
  114.     case POWER_OP:
  115.         return(pow(arg1, arg2));
  116.     }
  117. }
  118.  
  119. kw()
  120. {
  121.     if (NOT(OptionDown()))
  122.     {
  123.         while(NOT(ShiftDown()));
  124.         while(ShiftDown());
  125.     }
  126. }
  127.  
  128. es()
  129. {
  130.     ExitToShell();
  131. }
  132.  
  133. static
  134. Real
  135. FuncEval(arg, op)
  136. Real    arg;
  137. int        op;
  138. {
  139.     switch (op) {
  140.     case NEG_OP:
  141.         return(-arg);
  142.     case EXP_OP:
  143.         return(exp(arg));
  144.     case LOG_OP:
  145.         return(log(arg));
  146.     case LOG10_OP:
  147.         return(log10(arg));
  148.     case SQ_OP:
  149.         return(SQ(arg));
  150.     case SQRT_OP:
  151.         if (arg > 0)
  152.             return(sqrt(arg));
  153.         else
  154.             return(0.0);
  155.     case SIN_OP:
  156.         return(sin(arg));
  157.     case ASIN_OP:
  158.         return(asin(arg));
  159.     case COS_OP:
  160.         return(cos(arg));
  161.     case ACOS_OP:
  162.         return(acos(arg));
  163.     case TAN_OP:
  164.         return(tan(arg));
  165.     case ATAN_OP:
  166.         return(atan(arg));
  167.     case COTAN_OP:
  168.         return(cotan(arg));
  169.     case SINH_OP:
  170.         return(sinh(arg));
  171.     case COSH_OP:
  172.         return(cosh(arg));
  173.     case TANH_OP:
  174.         return(tanh(arg));
  175.     }
  176. }
  177.  
  178. /*-------------------------------------------------------------------------*/
  179.  
  180.  
  181. extern    Real        *funcResults;
  182. extern    Vector        *scalVectResults;
  183. extern    Point        *graphPoints;    /* same elements as funcResults */
  184.  
  185.  
  186. extern    Real    startX, startY;
  187. extern    Real    endX, endY;
  188. extern    Real    deltaX, deltaY;
  189. extern    int        numX, numY;
  190.  
  191. extern    Real    scale;
  192.  
  193. extern    Boolean        vectrsCurrent;
  194. extern    Boolean        pntsCurrent;
  195.  
  196. extern    Vector        maxVect, minVect;
  197. extern    Point    XaxisPt, YaxisPt, ZaxisPt;
  198. extern    Point    Origin;
  199. extern    Real    rotMatrx[3][3];
  200.  
  201. extern    Rect    graphRect;
  202. extern    Boolean        hideSurface, useHeight;
  203.  
  204. extern    Real    zScale;
  205. extern    Real    ceilgZ, floorZ;
  206.  
  207.  
  208. SRotatePoints(cAng, sAng, plane)
  209. register    Real    cAng, sAng;
  210. int        plane;
  211. {
  212.     register    long    i, numElmnts;
  213.     register    double    temp1, temp2;
  214.  
  215.     numElmnts = numX * numY;
  216.     if (plane EQ 1)
  217.     {
  218.         for (i = 0; i < numElmnts; i++)
  219.         {
  220.             temp1 = scalVectResults[i].y;
  221.             temp2 = scalVectResults[i].z;
  222.             scalVectResults[i].y = temp1 * cAng + temp2 * sAng;
  223.             scalVectResults[i].z = temp2 * cAng - temp1 * sAng;
  224.         }
  225.     }
  226.     else if (plane EQ 2)
  227.     {
  228.         for (i = 0; i < numElmnts; i++)
  229.         {
  230.             temp1 = scalVectResults[i].x;
  231.             temp2 = scalVectResults[i].z;
  232.             scalVectResults[i].x = temp1 * cAng - temp2 * sAng;
  233.             scalVectResults[i].z = temp2 * cAng + temp1 * sAng;
  234.         }
  235.     }
  236.     else if (plane EQ 3)
  237.     {
  238.         for (i = 0; i < numElmnts; i++)
  239.         {
  240.             temp1 = scalVectResults[i].x;
  241.             temp2 = scalVectResults[i].y;
  242.             scalVectResults[i].x = temp1 * cAng - temp2 * sAng;
  243.             scalVectResults[i].y = temp2 * cAng + temp1 * sAng;
  244.         }
  245.     }
  246.     else
  247.     {
  248.         for (i = 0; i < numElmnts; i++)
  249.         {
  250.             temp1 = scalVectResults[i].z;
  251.             temp2 = scalVectResults[i].y;
  252.             scalVectResults[i].z = temp1 * cAng - temp2 * sAng;
  253.             scalVectResults[i].y = temp2 * cAng + temp1 * sAng;
  254.         }
  255.     }
  256. }
  257.  
  258. SetPoints()
  259. {
  260. register    Real    _scale;
  261. register    int    xCnt, yCnt;
  262. register    long    offSet;
  263.     
  264.     SetNewScale();
  265.  
  266.     _scale = scale;
  267.     if (hideSurface)
  268.         CheckHideView();
  269.  
  270.     for (xCnt = 0; xCnt < numX; xCnt++)
  271.         for (yCnt = 0; yCnt < numY; yCnt++)
  272.         {
  273.             offSet = (long)xCnt * (long)numY + yCnt;
  274.             graphPoints[offSet].h = (int)(scalVectResults[offSet].y * _scale)
  275.                             + Origin.h;
  276.             graphPoints[offSet].v = (int)(-scalVectResults[offSet].z * _scale)
  277.                             + Origin.v;
  278.         }
  279.     GenAxes();
  280.     pntsCurrent = TRUE;
  281.     if (hideSurface AND useHeight)
  282.         SetHeightShades();
  283.     else if (hideSurface)
  284.         SetNormalShades();
  285. }
  286.  
  287. /*************************/
  288.  
  289. Uchar        *gridFace = NIL;
  290. extern        Real        cosSrc, sinSrc;
  291. extern        Boolean        scrnColor, colorNorms;
  292.  
  293.  
  294. SetNormalShades()
  295. {
  296. register    int        xCnt, yCnt, v;
  297. register    long    offSet;
  298.     Uchar    VectFace();
  299.  
  300.     colorNorms = scrnColor;
  301.     if (gridFace NEQ NIL)
  302.         free(gridFace);
  303.     gridFace = (Uchar *)NewPtr(sizeof(char) * (long)numX * numY);
  304.     if (MemErr)
  305.         return(FALSE);
  306.  
  307.     for (xCnt = 0; xCnt < numX-1; xCnt++)
  308.     {
  309.         for (yCnt = 0; yCnt < numY-1; yCnt++)
  310.         {
  311.             offSet = (long)xCnt * (long)numY + (long)yCnt;
  312.             v = VectFace(&scalVectResults[(long)(xCnt + 1) * numY + (long)yCnt],
  313.                     &scalVectResults[offSet],
  314.                     &scalVectResults[(long)xCnt * numY + (long)(yCnt + 1)]);
  315.             gridFace[offSet] = v;
  316.         }
  317.     }
  318. }
  319.  
  320. Uchar
  321. VectFace(a, b, c)
  322. Vector    *a, *b, *c;
  323. {
  324.     Vector    side1, side2, reslt;
  325.     Real    length, zCoor;
  326.     Real    VectMag();
  327. register    Real    temp1, temp2;
  328.  
  329.     SubtVector(a, b, &side1);
  330.     SubtVector(c, b, &side2);
  331.     CrossProduct(&side1, &side2, &reslt);
  332.  
  333.             temp1 = reslt.y;
  334.             temp2 = reslt.z;
  335.             reslt.y = temp1 * cosSrc + temp2 * sinSrc;
  336.             reslt.z = temp2 * cosSrc - temp1 * sinSrc;
  337.  
  338. /*if (reslt.x < 0)
  339.     return(0);
  340. */
  341.     length = VectMag(&reslt);
  342.     zCoor = reslt.z/length;
  343.     if (zCoor < 0)
  344.         zCoor = 0;
  345.     if (scrnColor)
  346.         zCoor = zCoor * 255.0;
  347.     else
  348.         zCoor = zCoor * 63.0;
  349.  
  350.     return((Uchar)round(zCoor));
  351. }
  352.  
  353.  
  354. /* cross-product of two vectors */
  355. CrossProduct(a, b, reslt)
  356. register    Vector    *a, *b, *reslt;
  357. {
  358.     reslt->x = a->y * b->z - a->z * b->y;
  359.     reslt->y = a->z * b->x - a->x * b->z;
  360.     reslt->z = a->x * b->y - a->y * b->x;
  361. }
  362.  
  363. /*** Difference and sum of two vectors;
  364.             result vector can be same as a or b ***/
  365. SubtVector(a, b, result)
  366. register    Vector    *a, *b, *result;
  367. {
  368.     result->x = a->x - b->x;
  369.     result->y = a->y - b->y;
  370.     result->z = a->z - b->z;
  371. }
  372.  
  373. Real
  374. VectMag(vectP)
  375. register    Vector    *vectP;
  376. {
  377.     return( sqrt( SQ(vectP->x) + SQ(vectP->y) + SQ(vectP->z) ) );
  378. }
  379.  
  380.  
  381. SetHeightShades()
  382. {
  383. register    int        xCnt, yCnt, v;
  384. register    long    offSet;
  385.     Real    min, max, sc;
  386.  
  387.     colorNorms = scrnColor;
  388.     if (gridFace NEQ NIL)
  389.         free(gridFace);
  390.     gridFace = (Uchar *)NewPtr(sizeof(char) * (long)numX * numY);
  391.     if (MemErr)
  392.         return(FALSE);
  393.  
  394.     FindFuncMaxMin(funcResults, &min, &max);
  395.     if (scrnColor)
  396.         sc = 255.0 / (max - min);
  397.     else
  398.         sc = 63.0 / (max - min);
  399.  
  400.     for (xCnt = 0; xCnt < numX-1; xCnt++)
  401.     {
  402.         for (yCnt = 0; yCnt < numY-1; yCnt++)
  403.         {
  404.             offSet = (long)xCnt * (long)numY + (long)yCnt;
  405.             gridFace[offSet] = (funcResults[offSet] - min) * sc;
  406.         }
  407.     }
  408. }
  409.  
  410. static
  411. FindFuncMaxMin(funcList, minPtr, maxPtr)
  412. register    Real    *funcList;
  413. Real        *minPtr, *maxPtr;
  414. {
  415. register    long    i, numElems;
  416. register    Real    max, min, funcVal;
  417.  
  418.     max = min = funcList[0];
  419.  
  420.     numElems = (long)numX * (long)numY;
  421.     for (i = 1; i < numElems; i++)
  422.     {
  423.         funcVal = funcList[i];
  424.         if (funcVal > max)
  425.             max = funcVal;
  426.         else if (funcVal < min)
  427.             min = funcVal;
  428.     }
  429.  
  430.     *minPtr = min;
  431.     *maxPtr = max;
  432. }
  433.  
  434.  
  435. /*************************/
  436.  
  437. SetVectrs()
  438. {
  439. register    int    xCnt, yCnt;
  440. register    long    offSet;
  441.     Real        ImposLimits();
  442. register    Real        xValue, yValue;
  443. register    Vector        *scalePtr;
  444.     Real    SdeltaX;
  445. register    Real    SdeltaY;
  446.     Vector    pntVect;
  447.  
  448.     SdeltaX = deltaX;
  449.     SdeltaY = deltaY;
  450.  
  451.     scalePtr = scalVectResults;
  452.  
  453.     xValue = startX;
  454.  
  455.     for (xCnt = 0; xCnt < numX; xCnt++)
  456.     {
  457.         yValue = startY;
  458.         pntVect.x = xValue;
  459.         for (yCnt = 0; yCnt < numY; yCnt++)
  460.         {
  461.             offSet = (long)xCnt * (long)numY + yCnt;
  462.             pntVect.y = yValue;
  463.             pntVect.z = (ImposLimits(funcResults[offSet]));
  464.             MatrxMul(rotMatrx, &pntVect, scalePtr++);
  465.             yValue += SdeltaY;
  466.         }
  467.         xValue += SdeltaX;
  468.     }
  469.     vectrsCurrent = TRUE;
  470. }
  471.  
  472.  
  473. static
  474. SetNewScale()
  475. {
  476.     DoubPoint    minPnt, maxPnt;
  477.     Real        scaleX, scaleY;
  478.     int            graphWidth, graphHeight;
  479.     DoubPoint    doubOrigin;
  480.  
  481.     FindMaxMin(scalVectResults, &minPnt, &maxPnt);
  482.  
  483.     graphWidth = graphRect.right - graphRect.left;
  484.     graphHeight = graphRect.bottom - graphRect.top;
  485.  
  486.     scaleX = (Real)(graphWidth) / (maxPnt.h - minPnt.h);
  487.     scaleY = (Real)(graphHeight) / (maxPnt.v - minPnt.v);
  488.     scale = MIN(scaleX, scaleY);
  489.  
  490.     maxPnt.h = maxPnt.h * scale;
  491.     maxPnt.v = maxPnt.v * scale;
  492.     minPnt.h = minPnt.h * scale;
  493.     minPnt.v = minPnt.v * scale;
  494.  
  495.     doubOrigin.h = ((graphWidth >> 1) + graphRect.left)
  496.                 - ( ((maxPnt.h - minPnt.h) / 2) + minPnt.h );
  497.     doubOrigin.v = ((graphHeight >> 1) + graphRect.top)
  498.             - ( ((maxPnt.v - minPnt.v) / 2) + minPnt.v );
  499.     Origin.h = round(doubOrigin.h);
  500.     Origin.v = round(doubOrigin.v);
  501. }
  502.  
  503. static
  504. FindMaxMin(graphVects, minPnt, maxPnt)
  505. register    Vector    *graphVects;
  506. DoubPoint    *minPnt, *maxPnt;
  507. {
  508. register    long    i, numElems;
  509. register    Real    max_h, max_v;
  510. register    Real    min_h, min_v;
  511.     Real    vertVal;
  512.  
  513.     max_h = min_h = graphVects[0].y;
  514.     max_v = min_v = -graphVects[0].z;
  515.  
  516.     numElems = (long)numX * (long)numY;
  517.     for (i = 1; i < numElems; i++)
  518.     {
  519.         if (graphVects[i].y > max_h)
  520.             max_h = graphVects[i].y;
  521.         else if (graphVects[i].y < min_h)
  522.             min_h = graphVects[i].y;
  523.         vertVal = -graphVects[i].z;
  524.         if (vertVal > max_v)
  525.             max_v = vertVal;
  526.         else if (vertVal < min_v)
  527.             min_v = vertVal;
  528.     }
  529.  
  530.     minPnt->h = min_h;
  531.     minPnt->v = min_v;
  532.     maxPnt->h = max_h;
  533.     maxPnt->v = max_v;
  534. }
  535.  
  536. Real
  537. ImposLimits(funcVal)
  538. Real    funcVal;
  539. {
  540.     Real    temp;
  541.     
  542.     temp = funcVal;
  543.     
  544.     if (temp > ceilgZ)
  545.         temp = ceilgZ;
  546.     else if (temp < floorZ)
  547.         temp = floorZ;
  548.  
  549.     return(temp * zScale);
  550. }
  551.  
  552. static
  553. ExpandRect(theRect, thePoint)
  554. register    DoubRect    *theRect;
  555. register    DoubPoint    *thePoint;
  556. {
  557.     if (thePoint->h < theRect->left)
  558.         theRect->left = thePoint->h;
  559.     else if (thePoint->h > theRect->right)
  560.         theRect->right = thePoint->h;
  561.  
  562.     if (thePoint->v < theRect->top)
  563.         theRect->top = thePoint->v;
  564.     else if (thePoint->v > theRect->bottom)
  565.         theRect->bottom = thePoint->v;
  566. }
  567.  
  568.  
  569. #ifdef    _MC68881_    /*** This function will be a macro calling ldexp() otherwise ***/
  570.  
  571. Real
  572. mldexp(a, n)
  573. Real    a;
  574. register    int        n;
  575. {
  576.     if (n EQ 0)
  577.         return(a);
  578.     else if (n > 0)
  579.         return(a * (Real)((long)2 << (n - 1)));
  580.     else
  581.         return(a / (Real)((long)2 << -(n + 1)));
  582. }
  583.  
  584. #endif
  585.  
  586. static
  587. GenAxes()
  588. {
  589.     Vector        axisVect;
  590.  
  591.     axisVect.x = 1000;
  592.     axisVect.y = 0;
  593.     axisVect.z = 0;
  594.     Conv3VtoPt(&axisVect, &XaxisPt);
  595.  
  596.     axisVect.x = 0;
  597.     axisVect.y = 1000;
  598.     Conv3VtoPt(&axisVect, &YaxisPt);
  599.  
  600.     axisVect.y = 0;
  601.     axisVect.z = 1000;
  602.     Conv3VtoPt(&axisVect, &ZaxisPt);
  603. }
  604.